package com.suitbim.commandserver.commandserver.manage;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.LongSerializationPolicy;
import com.suitbim.commandserver.commandserver.client.Cesium3DTilesConvertClient;
import com.suitbim.commandserver.commandserver.client.NavisworksCommandClient;
import com.suitbim.commandserver.commandserver.client.RevitCommandClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.concurrent.*;

@Component
public class BeanManage {

    @Value("${redis-message-queue.command-queue}")
    private String messageQueueName;

    @Value("${redis-message-queue.revit-command}")
    private String revitQueueName;

    @Value("${redis-message-queue.navisworks-command}")
    private String navisworksQueueName;

    @Value("${redis-message-queue.threeD-tiles-convert-command}")
    private String threeDTilesConvertCommand;

    @Value("${client.enable.revit}")
    private boolean revit;

    @Value("${client.enable.navisworks}")
    private boolean navisworks;

    @Value("${client.enable.threeD-tiles-convert}")
    private boolean threeDTilesConvert;

//    @Bean
//    public RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory redisConnectionFactory
//            , MainCommandReceiver mainCommandReceiver, RevitCommandReceiver revitCommandReceiver) {
//        RedisMessageListenerContainer redisMessageListenerContainer = new RedisMessageListenerContainer();
//        redisMessageListenerContainer.setConnectionFactory(redisConnectionFactory);
//        redisMessageListenerContainer.addMessageListener(mainCommandReceiver, new PatternTopic(messageQueueName));
//        redisMessageListenerContainer.addMessageListener(revitCommandReceiver, new PatternTopic(revitQueueName));
//        return redisMessageListenerContainer;
//    }

    @Bean
    public ThreadPoolExecutor threadPoolExecutor() {
        BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(100);
        ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 10, 1, TimeUnit.MINUTES, queue);
        pool.setRejectedExecutionHandler(new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                try {
                    //线程会阻塞在这里
                    queue.put(r);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        return pool;
    }

    @Bean
    public Gson gson() {
        Gson gson = new GsonBuilder().setLongSerializationPolicy(LongSerializationPolicy.STRING).create();
        return gson;
    }


    /**
     * 每有一个client定义一个这样的bean
     *
     * @param gson
     * @param threadPoolExecutor
     * @param redisTemplate
     * @return
     */

    @Bean
    public RevitCommandClient revitCommandClient(Gson gson, ThreadPoolExecutor threadPoolExecutor, RedisTemplate<String, String> redisTemplate) {
        RevitCommandClient revitCommandClient = null;
        if (revit) {
            revitCommandClient = new RevitCommandClient(gson, threadPoolExecutor, redisTemplate, revitQueueName);
            System.out.println("revit client start");
        }

        return revitCommandClient;
    }

    @Bean
    public NavisworksCommandClient navisworksCommandClient(Gson gson, ThreadPoolExecutor threadPoolExecutor, RedisTemplate<String, String> redisTemplate) {
        NavisworksCommandClient navisworksCommandClient = null;
        if (navisworks) {
            navisworksCommandClient = new NavisworksCommandClient(gson, threadPoolExecutor, redisTemplate, navisworksQueueName);
            System.out.println("navisworks client start");
        }
        return navisworksCommandClient;
    }

    @Bean
    public Cesium3DTilesConvertClient cesium3DTilesConvertClient(Gson gson, ThreadPoolExecutor threadPoolExecutor, RedisTemplate<String, String> redisTemplate) {
        Cesium3DTilesConvertClient cesium3DTilesConvertClient = null;
        if (threeDTilesConvert) {
            cesium3DTilesConvertClient = new Cesium3DTilesConvertClient(gson, threadPoolExecutor, redisTemplate, threeDTilesConvertCommand);
            System.out.println("threeDTilesConvertCommand client start");
        }
        return cesium3DTilesConvertClient;
    }
}
